<?php

namespace app\admin\controller\face;

use app\common\controller\Backend;
use app\common\library\AipFace;
use app\common\model\Device;
use app\common\model\DeviceAssociation;
use app\common\model\DeviceKey;
use app\common\model\Student;
use app\common\model\User;
use fast\Random;
use think\Config;
use think\Db;
use think\Exception;
use think\exception\HttpResponseException;
use think\Log;
use think\Response;

/**
 * 人脸库--班级学生
 *
 * Class Classes
 * @package app\admin\controller\face
 */
class Classes extends Backend
{
    /**
     * @var \app\common\model\Classes
     */
    protected $model = null;
    protected $searchFields = 'name';
    protected $noNeedRight = ['searchList', 'cxSelect', 'sync', 'import', 'upload', 'students'];
    //protected $dataLimit = true;
    protected $schoolLimit = true;

    public function _initialize()
    {
        parent::_initialize();
        $this->model = model('Classes');
    }

    /**
     * 查看
     */
    public function index()
    {
        //设置过滤方法
        $this->request->filter(['strip_tags']);
        if ($this->request->isAjax()) {
            //如果发送的来源是Selectpage，则转发到Selectpage
            if ($this->request->request('keyField')) {
                return $this->selectpage();
            }
            list($where, $sort, $order, $offset, $limit) = $this->buildparams();
            $total = $this->model
                ->with('grade')
                ->with('school')
                ->with('garden')
                ->with('building')
                ->with('classroom')
                ->where($where)
                ->order($sort, $order)
                ->count();

            $list = $this->model
                ->with('grade')
                ->with('school')
                ->with('garden')
                ->with('building')
                ->with('classroom')
                ->where($where)
                ->order($sort, $order)
                ->limit($offset, $limit)
                ->select();

            if ($list) {
                $list = collection($list)->toArray();

                //$school_ids = $this->auth->getChildrenSchoolIds(true);
                $classes_ids = array_column($list, 'id');
                /*$result = \app\common\model\Student::whereIn('class_id', $classes_ids)
                    ->whereIn('school_id', $school_ids)
                    ->field('class_id,count(*) count')
                    ->group('class_id')
                    ->select();*/
                $result = \app\common\model\ClassStudent::alias('a')
                    ->join('__STUDENT__ b', 'b.id = a.student_id')
                    ->whereIn('a.class_id', $classes_ids)
                    ->field('a.class_id,count(*) count')
                    ->group('a.class_id')
                    ->select();
                $student_data = [];
                foreach ($result as $key => $value) {
                    $student_data[$value['class_id']] = $value['count'];
                }

                foreach ($list as $key => $value) {
                    $list[$key]['student_count'] = isset($student_data[$value['id']]) ? $student_data[$value['id']] : 0;

                    /*$device_association = DeviceAssociation::where('class_id', $value['id'])->find();
                    if ($device_association) {
                        $device_key = DeviceKey::where('id', $device_association['device_id'])->find();
                        if ($device_key) {
                            $list[$key]['device_key'] = $device_key['key'];
                        }
                    }*/
                }

            }
            $result = array("total" => $total, "rows" => $list);

            return json($result);
        }

        $this->assignconfig('admin', ['socket_id' => strtoupper(md5(uuid()))]);

        return $this->view->fetch();
    }
    
    public function students()
    {
        $class_id = $this->request->request('ids', 0);

        $this->assignconfig('admin', ['class_id' => $class_id]);
        return $this->view->fetch();
    }

    public function sync()
    {
        $class_id = $this->request->request('id');
        if (!$class_id) {
            $this->error('参数错误');
        }

        $device_association = DeviceAssociation::where('class_id', $class_id)->find();
        if (!$device_association || !$device_association['device_id']) {
            $this->error('未绑定班牌');
        }

        $device = Device::where('id', $device_association['device_id'])->where('status', Device::ACTIVATED)->find();
        if (!$device) {
            $this->error('班牌未激活');
        }

        $this->success('', $device['device_code']);

//        // 建立socket连接到内部推送端口
//        $client = stream_socket_client('tcp://socket.uxuj.cn:2123', $errno, $errmsg, 1);
//        // 推送的数据，包含uid字段，表示是给这个uid推送
//        $to = $device['device_code'];
//        $data = array(
//            'type' => 'publish',
//            'content' => ['event'=>'pull_faces', 'class_id' => $class_id, 'key' => $to],
//            'to' => $to
//        );
//
//        // 发送数据，注意2123端口是Text协议的端口，Text协议需要在数据末尾加上换行符
//        fwrite($client, json_encode($data) . "\n");
//        // 读取推送结果
//        $result = fread($client, 8192);
//        dd($result);
    }

    public function import()
    {
        return $this->view->fetch();
    }

    public function upload()
    {
        $class_id = $this->request->request('class_id');
        if (!$class_id) {
            $this->error(__('请选择班级'));
        }

        Config::set('default_return_type', 'json');
        $file = $this->request->file('file');
        if (empty($file)) {
            $this->error(__('No file upload or server upload limit exceeded'));
        }

        //判断是否已经存在附件
        $sha1 = $file->hash();
        $extparam = $this->request->post();

        $upload = Config::get('upload');

        preg_match('/(\d+)(\w+)/', $upload['maxsize'], $matches);
        $type = strtolower($matches[2]);
        $typeDict = ['b' => 0, 'k' => 1, 'kb' => 1, 'm' => 2, 'mb' => 2, 'gb' => 3, 'g' => 3];
        $size = (int)$upload['maxsize'] * pow(1024, isset($typeDict[$type]) ? $typeDict[$type] : 0);
        $fileInfo = $file->getInfo();
        $suffix = strtolower(pathinfo($fileInfo['name'], PATHINFO_EXTENSION));
        $suffix = $suffix ? $suffix : 'file';

        $mimetypeArr = explode(',', strtolower($upload['mimetype']));
        $typeArr = explode('/', $fileInfo['type']);

        //验证文件后缀
        if ($upload['mimetype'] !== '*' &&
            (
                !in_array($suffix, $mimetypeArr)
                || (stripos($typeArr[0] . '/', $upload['mimetype']) !== false && (!in_array($fileInfo['type'], $mimetypeArr) && !in_array($typeArr[0] . '/*', $mimetypeArr)))
            )
        ) {
            $this->error(__('图片格式错误'));
        }

        list($file_name) = explode('.', $fileInfo['name']);
        try {
            list($student_name, $student_number) = explode('-', $file_name);
            if ($student_name && $student_number) {
                $student = Student::get(['name' => $student_name, 'number' => $student_number, 'class_id' => $class_id]);
                if (!$student) {
                    $this->error(' 未匹配到学生');
                }
            } else {
                $this->error(' 未匹配到学生');
            }
        } catch (Exception $e) {
            $student = Student::get(['name' => $file_name, 'class_id' => $class_id]);
            if (!$student) {
                $this->error(' 未匹配到学生');
            }
        }

        $replaceArr = [
            '{year}'     => date("Y"),
            '{mon}'      => date("m"),
            '{day}'      => date("d"),
            '{hour}'     => date("H"),
            '{min}'      => date("i"),
            '{sec}'      => date("s"),
            '{random}'   => Random::alnum(16),
            '{random32}' => Random::alnum(32),
            '{filename}' => $suffix ? substr($fileInfo['name'], 0, strripos($fileInfo['name'], '.')) : $fileInfo['name'],
            '{suffix}'   => $suffix,
            '{.suffix}'  => $suffix ? '.' . $suffix : '',
            '{filemd5}'  => md5_file($fileInfo['tmp_name']),
        ];
        $savekey = $upload['savekey'];
        $savekey = str_replace(array_keys($replaceArr), array_values($replaceArr), $savekey);
        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName = substr($savekey, strripos($savekey, '/') + 1);
        $splInfo = $file->validate(['size' => $size])->move(ROOT_PATH . '/public' . $uploadDir, $fileName);
        if ($splInfo) {
            if (isset($student)) {
                Db::startTrans();
                try {
                    $avatar = $uploadDir . $splInfo->getSaveName();
                    $student->avatar = $avatar;
                    $flag = $student->save();
                    if (!$flag) {
                        $this->error('保存失败');
                    }
                    if ($student->user_id) {
                        User::where('id', $student->user_id)->update(['avatar' => $avatar]);
                    }

                    $image = config('app_url') . $avatar;
                    $image_type = 'URL';
                    $group_id = 'mp';
                    $user_id = $student->user_id;
                    $options = array();
                    $options["user_info"] = json_encode(['user_id' => $user_id, 'role' => 'student', 'student_id' =>  $student->id]);
                    $options["action_type"] = "REPLACE";
                    $ret = AipFace::instance()->addUser($image, $image_type, $group_id, $user_id, $options);

                    if ($ret['error_code']) {
                        Db::rollback();
                        return $this->error($ret['error_msg']);
                    } else {
                        \app\common\model\User::where('id', $user_id)->update(['face_token' => $ret['result']['face_token']]);
                        $imagewidth = $imageheight = 0;
                        if (in_array($suffix, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'])) {
                            $imgInfo = getimagesize($splInfo->getPathname());
                            $imagewidth = isset($imgInfo[0]) ? $imgInfo[0] : $imagewidth;
                            $imageheight = isset($imgInfo[1]) ? $imgInfo[1] : $imageheight;
                        }

                        $params = array(
                            'admin_id'    => (int)$this->auth->id,
                            'user_id'     => 0,
                            'filesize'    => $fileInfo['size'],
                            'imagewidth'  => $imagewidth,
                            'imageheight' => $imageheight,
                            'imagetype'   => $suffix,
                            'imageframes' => 0,
                            'mimetype'    => $fileInfo['type'],
                            'url'         => $uploadDir . $splInfo->getSaveName(),
                            'uploadtime'  => time(),
                            'storage'     => 'local',
                            'sha1'        => $sha1,
                            'extparam'    => json_encode($extparam),
                        );
                        $attachment = model("attachment");
                        $attachment->data(array_filter($params));
                        $attachment->save();

                        Db::commit();

                        $this->success(__(' 匹配成功'), null, $params);
                    }

                } catch (Exception $e) {
                    Db::rollback();
                    $this->error($e->getMessage());
                }

            } else {
                $this->error('未匹配到学生');
            }

        } else {
            // 上传失败获取错误信息
            $this->error($file->getError());
        }
    }

}
